package com.fengxu.gamescript.jsengine.api;

import android.graphics.Color;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;

import androidx.core.widget.NestedScrollView;

import com.fengxu.gamescript.R;
import com.fengxu.gamescript.data.GlobalData;
import com.fengxu.gamescript.data.LogChangeType;
import com.fengxu.gamescript.data.LogEvent;
import com.fengxu.gamescript.jsengine.annotation.JsCodeTip;
import com.fengxu.gamescript.jsengine.annotation.JsObject;
import com.fengxu.gamescript.jsengine.core.JsRunnerLog;
import com.fengxu.gamescript.jsengine.exception.ScriptRunningException;
import com.fengxu.gamescript.ui.base.BaseActivity;
import com.fengxu.gamescript.ui.main.MainActivity;
import com.fengxu.gamescript.util.PermissionUtils;
import com.xuexiang.xui.utils.DensityUtils;
import com.yhao.floatwindow.FloatWindow;
import com.yhao.floatwindow.IFloatWindow;
import com.yhao.floatwindow.MoveType;
import com.yhao.floatwindow.Screen;
import com.yhao.floatwindow.ViewStateListener;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import kotlin.Unit;

/**
 * 控制台
 */
@JsObject(name = "console")
public class Console extends AbstractJsObject {

    @Override
    public String getNameInJs() {
        return "console";
    }

    // 当前运行环境标识
    private String name;

    // 悬浮窗组件
    private View consoleView;

    // 日志变化事件监听器
    private LogChangedEvent logChangedEvent;



    public Console(Global global){
        super(global);
        name = Thread.currentThread().getName();
    }

    /**
     * 初始化控制台组件
     * @return 控制台组件
     */
    private void loadConsoleView(){
        consoleView = View.inflate(global.getmContext(), R.layout.flow_console, null);
        // 设置标题
        ((TextView)consoleView.findViewById(R.id.console_title)).setText(name);
        // 设置关闭控制台事件
        consoleView.findViewById(R.id.console_close).setOnClickListener(v->{
            close();
        });
        // 首次同步日志
        for (JsRunnerLog log : GlobalData.INSTANCE.getLogList()) {
            addLogView(log);
        }
        // 初始化日志监听
        logChangedEvent = new LogChangedEvent();
        // 订阅日志事件
        GlobalData.INSTANCE.getLogChanged().add(logChangedEvent);
    }

    // 日志变化实现类
    private class LogChangedEvent implements LogEvent{
        @Override
        public void changed(@NotNull LogChangeType type, @Nullable JsRunnerLog log) {
            if(type == LogChangeType.Add && log.getLogLevel() == JsRunnerLog.LogLevel.Info){
                global.getUiHandle().post(()->{
                    addLogView(log);
                });
            }
            if(type == LogChangeType.Clear){
                global.getUiHandle().post(()->{
                    ((LinearLayout)consoleView.findViewById(R.id.console_logLayout)).removeAllViews();
                });
            }
        }
    }


    /**
     * 添加一条日志组件到布局中
     * @param log 日志
     */
    private void addLogView(JsRunnerLog log){
        // 只添加用户打印的info类型日志
        if(log == null || log.getLogLevel() != JsRunnerLog.LogLevel.Info) return;
        TextView tv = new TextView(global.getmContext().getApplicationContext());
        LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.WRAP_CONTENT
        );
        lp.bottomMargin =  DensityUtils.dp2px(10F);
        tv.setText(log.getMsg());
        tv.setLayoutParams(lp);
        tv.setTextSize(14F);
        tv.setTextColor(Color.parseColor("#FFFFFF"));
        try {
            ((LinearLayout)consoleView.findViewById(R.id.console_logLayout)).addView(tv);
            // 设置滚动到底部
            global.getUiHandle().post(()->{
                ((NestedScrollView)consoleView.findViewById(R.id.console_scrollView)).fullScroll(ScrollView.FOCUS_DOWN);
            });
        }catch (Exception e){/*ignore*/}
    }

    /**
     * 清空控制台
     */
    @JsCodeTip
    public void clear(){
        GlobalData.INSTANCE.clearAllLog();
    }

    /**
     * 显示控制台悬浮窗
     */
    @JsCodeTip
    public void show(){
        if(!PermissionUtils.INSTANCE.checkFloatPermission(global.getmContext())){
            throw new ScriptRunningException("未赋予悬浮窗权限!");
        }
        close();
        global.getUiHandle().post(()->{
            loadConsoleView();
            FloatWindow.with(global.getmContext().getApplicationContext())
                    .setWidth(Screen.width, 0.6F)
                    .setHeight(Screen.height, 0.35F)
                    .setX(50)
                    .setY(100)
                    .setMoveType(MoveType.inactive)
                    .setViewStateListener(new ConsoleStateChange())
                    .setView(consoleView)
                    .setTag(name)
                    .build();
            FloatWindow.get(name).show();
        });
    }


    /**
     * 打印一条日志
     * @param msg 要打印的消息
     */
    @JsCodeTip
    public void log(Object msg){
        Log.i(name, "===========printLog===============>" + msg);
        GlobalData.INSTANCE.addLog(new JsRunnerLog(name, JsRunnerLog.LogLevel.Info, msg.toString()));
    }

    /**
     * 关闭控制台
     */
    @JsCodeTip
    public void close(){
        global.getUiHandle().post(()->{
            if(FloatWindow.get(name) != null){
                FloatWindow.destroy(name);
                GlobalData.INSTANCE.getLogChanged().remove(logChangedEvent);
                consoleView = null;
            }
        });
    }

    /**
     * 实现console悬浮窗状态监听
     */
    private class ConsoleStateChange implements ViewStateListener{

        @Override
        public void onPositionUpdate(int x, int y) {

        }

        @Override
        public void onShow() {
        }

        @Override
        public void onHide() {
            IFloatWindow floatWindow = FloatWindow.get(name);
            if(floatWindow != null){
                floatWindow.show();
            }
        }

        @Override
        public void onDismiss() {

        }

        @Override
        public void onMoveAnimStart() {

        }

        @Override
        public void onMoveAnimEnd() {

        }

        @Override
        public void onBackToDesktop() {
        }
    }

}
